/*
 * Copyright (c) 2012 Aleksander Zotov, Benedikt Markt, Aliaksei Babkovich
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *  
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 *  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 *  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 *  THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package utils;

import java.util.Date;
/**
 * This package contains methods to validate input data
 * 
 * @author Benedikt Markt
 *
 */
public class Validator {

	/**
	 * maximum length of an username
	 */
	private static final int MAX_USERNAME_LENGTH = 12;
	/**
	 * minimum length of user password
	 */
	private static final int MIN_PASSWORD_LENGTH = 8;
	/**
	 * maximul length of user password
	 */
	private static final int MAX_PASSWORD_LENGTH = 18;
	/**
	 * maximum length of a simulation name
	 */
	private static final int MAX_SIMNAME_LENGTH = 20;
	/**
	 * maximum length of a simulation description
	 */
	private static final int MAX_SIMDESCRIPTION_LENGTH = 300;

	/**
	 * Checks if the given string is a valid simulation name
	 * 
	 * @param name
	 *            the string to check
	 * @return true if valid, otherwise false
	 */
	public static Boolean isValidSimName(String name) {
		return name.length() <= MAX_SIMNAME_LENGTH;
	}

	/**
	 * Checks if the given string is a valid simulation description
	 * 
	 * @param description
	 *            the string to check
	 * @return true if valid, otherwise false
	 */
	public static Boolean isValidSimDescription(String description) {
		return description.length() <= MAX_SIMDESCRIPTION_LENGTH;
	}

	/**
	 * Checks if the given string is a valid date
	 * 
	 * @param date
	 *            the string to check
	 * @return true if valid, otherwise false
	 */
	public static Boolean isValidDate(String date) {
		DateUtils dateUtils = new DateUtils();
		return dateUtils.isValidDate(date);
	}

	/**
	 * Checks if the given strings are valid dates and start is before end
	 * 
	 * @param startStr
	 *            the start date as string
	 * @param endStr
	 *            the end date as string
	 * @return true if valid, otherwise false
	 */
	public static Boolean isValidStartEnd(String startStr, String endStr) {
		Date start = new DateUtils().toDate(startStr);
		Date end = new DateUtils().toDate(endStr);
		return start.before(end);
	}

	/**
	 * Checks if the given string is a valid distance
	 * 
	 * @param distance
	 *            the string to check
	 * @return true if valid, otherwise false
	 */
	public static Boolean isValidDistance(String distance) {
		String pattern = "^(\\+)?([0-9]*(\\.|,)?([0-9]+))$";
		distance.trim();
		return distance.matches(pattern);
	}

	/**
	 * Checks if the give string array contains valid tle data
	 * 
	 * @param tle
	 *            the string array with the tle data
	 * @return true if contains valid tle data, otherwise false
	 */
	public static Boolean isValidTLE(String[] tle) {
		if (tle.length < 2) {
			return false;
		}

		boolean containsValid = false;
		boolean threeLE = !tleChecksum(tle[0]);
		for (int i = 0; i < tle.length; i++) {
			if (threeLE) {
				if (tle.length > i + 1) {
					i++;
				} else
					return false;
			}
			if (!tleChecksum(tle[i])) {
				return false;
			}
			if (tle.length > i) {
				i++;
			} else
				return false;
			if (!tleChecksum(tle[i])) {
				return false;
			} else {
				containsValid = true;
			}
		}
		return containsValid;
	}

	/**
	 * Checks if the given string is a valid username
	 * 
	 * @param username
	 *            the string to check
	 * @return true if valid, otherwise false
	 */
	public static Boolean isValidUsername(String username) {
		return username.length() <= MAX_USERNAME_LENGTH;
	}

	/**
	 * Checks if the given string is a valid password
	 * 
	 * @param password
	 *            the string to check
	 * @return true if valid, otherwise false
	 */
	public static Boolean isValidPassword(String password) {

		/*
		 * regular expression to check if the password contains at least one
		 * lower-case and one upper-case letter, one number and one special
		 * character
		 */
		String pattern = "^(?=.*[A-Z])(?=.*[\\W])(?=.*[0-9])(?=.*[a-z]).{"
				+ MIN_PASSWORD_LENGTH + "," + MAX_PASSWORD_LENGTH + "}$";
		return password.matches(pattern);
	}

	/**
	 * Checks the checksum of a tle line
	 * 
	 * @param line
	 *            the string to check
	 * @return true if valid, otherwise false
	 */
	private static boolean tleChecksum(String line) {
		if (line.length() == 69) {
			int checksum = 0;

			for (int i = 0; i < 68; i++) {
				if (Character.isDigit(line.charAt(i))) {
					checksum += (int) (line.charAt(i) - '0');
				} else if (line.charAt(i) == '-') {
					checksum++;
				}
			}
			return ((int) (line.charAt(68) - '0')) == checksum % 10;
		} else {
			return false;
		}
	}
}
